import { Layout } from '@/layout';

export const meta = {
  title: 'How can I load fonts in React Router?',
  description: 'A guide to load custom fonts in React Router',
  slug: 'react-router-load-fonts',
  category: 'tooling',
  tags: ['fonts', 'Google fonts'],
  created_at: 'July 23, 2024',
  last_updated_at: 'July 23, 2024',
};

export default Layout(meta);

## Loading local fonts

Create the following folder structure (the example with Roboto custom font):

```plaintext
Roboto/
├─ Roboto-Bold.woff2
├─ Roboto-Heavy.woff2
├─ Roboto.css
```

In `Roboto.css` file, add the following code:

```css
@font-face {
  font-family: 'Roboto';
  src: url('./Roboto-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
}

@font-face {
  font-family: 'Roboto';
  src: url('./Roboto-Heavy.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
}
```

Then import `Roboto.css` file at the root of your application and
add the font to your [theme](https://mantine.dev/theming/theme-object/):

```tsx
import '@mantine/core/styles.css';
import './Roboto/styles.css';

import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from 'react-router';
import {
  ColorSchemeScript,
  createTheme,
  DEFAULT_THEME,
  MantineProvider,
  mantineHtmlProps,
} from '@mantine/core';

const theme = createTheme({
  fontFamily: 'Roboto, sans-serif',
  fontFamilyMonospace: 'Monaco, Courier, monospace',
  headings: {
    // Use default theme if you want to provide default Mantine fonts as a fallback
    fontFamily: `Roboto, ${DEFAULT_THEME.fontFamily}`,
  },
});

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" {...mantineHtmlProps}>
      <head>
        <meta charSet="utf-8" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1"
        />
        <Meta />
        <Links />
        <ColorSchemeScript />
      </head>
      <body>
        <MantineProvider theme={theme}>{children}</MantineProvider>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

export default function App() {
  return <Outlet />;
}
```

## Load fonts from Google Fonts

Selects fonts you want to use at [Google Fonts](https://fonts.google.com/) and copy
HTML code snippet. For example, to load [Roboto](https://fonts.google.com/specimen/Roboto)
font, the code you receive from Google Fonts will look something like this:

```html
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
  rel="preconnect"
  href="https://fonts.gstatic.com"
  crossorigin=""
/>
<link
  href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
  rel="stylesheet"
/>
```

Add the code to the `<head />` of your application `root.tsx` file.
The code will look something like this:

```tsx
import '@mantine/core/styles.css';
import './Roboto/styles.css';

import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from 'react-router';
import {
  ColorSchemeScript,
  createTheme,
  DEFAULT_THEME,
  MantineProvider,
} from '@mantine/core';

const theme = createTheme({
  fontFamily: 'Roboto, sans-serif',
  fontFamilyMonospace: 'Monaco, Courier, monospace',
  headings: {
    // Use default theme if you want to provide default Mantine fonts as a fallback
    fontFamily: `Roboto, ${DEFAULT_THEME.fontFamily}`,
  },
});

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1"
        />
        <Meta />
        <Links />
        <ColorSchemeScript />
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link
          rel="preconnect"
          href="https://fonts.gstatic.com"
          crossOrigin=""
        />
        <link
          href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
          rel="stylesheet"
        />
      </head>
      <body>
        <MantineProvider theme={theme}>{children}</MantineProvider>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

export default function App() {
  return <Outlet />;
}
```
